import type { Metadata } from 'next'; import Link from 'next/link'; import { notFound } from 'next/navigation'; import { ExternalLink, AlertTriangle } from 'lucide-react'; import { PageHeader, Section, KV, Note } from '@/components/ui/section'; import { Badge, ClaimBadge } from '@/components/ui/badge'; import { EmptyState } from '@/components/ui/empty-state'; import { Freshness } from '@/components/ui/freshness'; import { SourceBadge } from '@/components/ui/source-badge'; import { EvidenceTable } from '@/components/data/evidence-table'; import { Pager } from '@/components/ui/pager'; import { getPublicationByPmid, publicationEntities } from '@/lib/queries/publications'; import { evidenceForPublication, evidenceForPublicationCount, EVIDENCE_PAGE_SIZE } from '@/lib/queries/evidence'; import { loadProvenance } from '@/lib/queries/provenance'; import { fmtDate, fmtInt, humanize, truncate } from '@/lib/format'; import { pageInfo } from '@/lib/pagination'; import { int, type SP } from '@/lib/search-params'; export const revalidate = 3600; export async function generateMetadata({ params }: { params: Promise<{ pmid: string }> }): Promise { const p = await getPublicationByPmid((await params).pmid); return p ? { title: `${truncate(p.title, 80)} — PMID ${p.pmid}`, description: truncate(p.abstract ?? p.title, 160), robots: p.retracted ? { index: false } : undefined, alternates: { canonical: `/publication/${p.pmid}` } } : { title: 'Publication' }; } export default async function PublicationPage({ params, searchParams }: { params: Promise<{ pmid: string }>; searchParams: Promise }) { const { pmid } = await params; if (!/^\d{1,10}$/.test(pmid)) notFound(); const p = await getPublicationByPmid(pmid); if (!p) notFound(); const sp = await searchParams; const evTotal = await evidenceForPublicationCount(pmid); const ev = pageInfo(int(sp, 'evPage', 1, 1, 100_000), EVIDENCE_PAGE_SIZE, evTotal); const [edges, evidence] = await Promise.all([publicationEntities(p.id), evTotal ? evidenceForPublication(pmid, { page: ev.page, pageSize: ev.pageSize }) : Promise.resolve([])]); const prov = await loadProvenance(evidence.map((e) => e.provenance_id)); const validated = edges.filter((e) => e.status === 'validated'); const candidates = edges.filter((e) => e.status === 'candidate'); return (
{p.retracted ? (

This publication has been retracted.

{p.retraction_notice ?

{p.retraction_notice}

: null}

Evidence relying on it is flagged; treat all findings below as withdrawn.

) : null}

{p.authors.map((a) => a.name).join(', ') || 'Authors not recorded'}

{p.journal ? {p.journal} : null} {p.pub_date ? {fmtDate(p.pub_date)} : p.pub_year ? {p.pub_year} : null} PMID {p.pmid} {p.doi ? ( doi:{p.doi} ) : null} {p.pmcid ? {p.pmcid} : null} {p.publication_types.map((t) => ( {t} ))}
{p.abstract ? ( <>

{truncate(p.abstract, 300)}

Read on PubMed ) : ( No abstract stored.{' '} Read on PubMed )}
{edges.length ? (
{[ { label: 'Validated', rows: validated, tone: 'ok' as const }, { label: 'Candidate', rows: candidates, tone: 'warn' as const }, ] .filter((g) => g.rows.length) .map((g) => (

{g.label} {g.rows.length}

    {g.rows.map((e) => (
  • {e.entity_type} {e.href ? ( {e.label ?? e.entity_id} ) : ( {e.label ?? e.entity_id} )} {e.method} {e.confidence != null ? {e.confidence.toFixed(2)} : null}
  • ))}
))}
) : ( No entity link recorded for this publication. )} {p.nct_ids.length ? (

Registered trials {p.nct_ids.map((n) => ( {n} ))}

) : null}
EVIDENCE_PAGE_SIZE ? `${EVIDENCE_PAGE_SIZE} items per page.` : undefined}> {evidence.length ? ( <> Showing {fmtInt(ev.from)}–{fmtInt(ev.to)} of {fmtInt(evTotal)} evidence items } /> `/publication/${p.pmid}${pg > 1 ? `?evPage=${pg}` : ''}#evidence`} label="Evidence pages" noun="evidence items" /> ) : ( No curated evidence item cites this publication. )}
); }